#include <iostream>
#include <string>
#include <signal.h>

#include "sock.hpp"
#include "protocol.hpp"

void usage(std::string proc)
{
  std::cout << "usage:\n\t" << proc << ": need port" << std::endl;
}

void server_IO(int sock)
{
  //原生的方法,没有明显的序列化和反序列化的过程
  //处理的过程
  //request -> 分析处理 -> 构建response -> sent(response) -> close(sock)
  
  while(true)
  {
    //1.读取请求
    request_t req;
    ssize_t ret = read(sock, &req, sizeof(req));
    if (ret == sizeof(req))
    { 
      //2.分析请求和计算结果
      response_t resp = {0, 0};

      switch(req.op)
      {
        case '+':
          resp.result = req.left + req.right;
          break;

        case '-':
          resp.result = req.left - req.right;
          break;

        case '*':
          resp.result = req.left * req.right;
          break;

        case '/':
          if (req.right == 0)
          {
            //代表除0异常
            resp.code = -1;
          }
          else
          {
            resp.result = req.left / req.right;
          }
          break;

        case '%':
          if (req.right == 0)
          {
            //代表模0异常
            resp.code = -2;
          }
          else
          {
            resp.result = req.left % req.right;
          }
          break;

        default:
          //代表操作符号异常
          resp.code = -3;
          break;
      }
      std::cout << "server# " << req.left << " " << req.op << " " << req.right << std::endl;

      //构建响应,并进行返回
      write(sock, &resp, sizeof(resp));

    }
    else if(ret == 0)
    {
      std::cout << "client quit!" << std::endl;
      break;
    }
    else
    {
      perror("read");
      std::cout << "errno : " << errno << std::endl;
      break;
    }
  }
}

void* handle_request(void* args)
{
  pthread_detach(pthread_self());
  int sock = *(int*)args;
  delete (int*)args;
  args = nullptr;

  server_IO(sock);
  close(sock);
  return nullptr;
}

int main(int argc, char* argv[])
{
  if (argc != 2)
  {
    usage(argv[0]);
    return 1;
  }

  uint16_t port = atoi(argv[1]);
  int listen_sock = Sock::Socket();
  Sock::Bind(listen_sock, port);
  int back_log = 5;
  Sock::Listen(listen_sock, back_log);

  signal(SIGCHLD, SIG_IGN);

  while(true)
  {
    int new_sock = Sock::Accept(listen_sock);
    if (new_sock >= 0)
    {
      int* pram = new int(new_sock);
      pthread_t tid;
      pthread_create(&tid, nullptr, handle_request, pram);
    }
    else
    {
      continue;
    }
  }
  return 0;
}
